package tech.edwardvan.quartzdemo.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tech.edwardvan.quartzdemo.entity.Task;
import tech.edwardvan.quartzdemo.common.ScheduleConstant;
import tech.edwardvan.quartzdemo.job.DemoJob;
import tech.edwardvan.quartzdemo.service.IScheduleService;

import java.util.ArrayList;
import java.util.List;


/**
 * @author EdwardVan
 */
@Service
@Slf4j
public class ScheduleServiceImpl implements IScheduleService {

    @Autowired
    private Scheduler scheduler;

    @Override
    public Task getTask(String taskId) throws SchedulerException {
        JobKey jobKey = new JobKey(taskId, ScheduleConstant.DEFAULT_JOB_GROUP_NAME);
        checkJobKey(jobKey);
        return Task.getInstance(scheduler.getJobDetail(jobKey));
    }

    @Override
    public void addTask(Task task) throws SchedulerException {
        JobDetail jobDetail = JobBuilder.newJob(DemoJob.class)
                .withIdentity(task.getTaskId(), ScheduleConstant.DEFAULT_JOB_GROUP_NAME)
                .withDescription(task.getDesc())//任务的描述
                .storeDurably()//指明作业就算没有绑定Trigger仍保留在Quartz的JobStore中
                .usingJobData(new JobDataMap(task.getDataMap()))
                .build();
        //将job添加到调度中
        scheduler.addJob(jobDetail, false);

        List<String> crons = createTriggers(task);
        log.info("成功启动({})定时任务,定时表达式为:{}", task.getTaskId(), crons);
    }

    /**
     * 通过任务创建触发器
     */
    private List<String> createTriggers(Task task) throws SchedulerException {
        List<String> crons = task.getCrons();
        if (CollectionUtil.isNotEmpty(crons)) {
            for (int i = 0; i < crons.size(); i++) {
                String cron = crons.get(i);
                String triggerName = task.getTaskId() + ScheduleConstant.TRIGGER_SEPARATOR + i;
                Trigger trigger = TriggerBuilder.newTrigger()
                        .withIdentity(triggerName, ScheduleConstant.DEFAULT_TRIGGER_GROUP_NAME)
                        .withDescription(task.getDesc())
                        .forJob(task.getTaskId(), ScheduleConstant.DEFAULT_JOB_GROUP_NAME)//使用scheduleJob(Trigger)加入的Trigger必须指明JobName与JobGroup
                        .withSchedule(CronScheduleBuilder.cronSchedule(cron)).build();
                //用scheduleJob(Trigger)加入的Trigger必须指明JobName与JobGroup
                scheduler.scheduleJob(trigger);
            }
        }
        return crons;
    }

    /**
     * 检查jobKey是否正确
     */
    private void checkJobKey(JobKey jobKey) throws SchedulerException {
        if (!scheduler.checkExists(jobKey)) {
            throw new SchedulerException("taskId不存在");
        }
    }


    @Override
    public void updateTask(Task task) throws SchedulerException {
        //通过taskId创建JobKey
        JobKey jobKey = new JobKey(task.getTaskId(), ScheduleConstant.DEFAULT_JOB_GROUP_NAME);
        checkJobKey(jobKey);
        //移除调度器
        removeTriggers(jobKey);
        //创建调度器
        createTriggers(task);
    }

    @Override
    public void deleteTask(String taskId) throws SchedulerException {
        //通过taskId创建JobKey
        JobKey jobKey = new JobKey(taskId, ScheduleConstant.DEFAULT_JOB_GROUP_NAME);
        checkJobKey(jobKey);
        removeTriggers(jobKey);
        scheduler.deleteJob(jobKey);// 删除任务
        log.info("成功删除({})定时任务", taskId);
    }

    /**
     * 通过jobKey移除触发器
     */
    private void removeTriggers(JobKey jobKey) throws SchedulerException {
        //通过jobKey获取对应的Trigger信息
        List<? extends Trigger> triggersOfJob = scheduler.getTriggersOfJob(jobKey);
        if (CollectionUtil.isNotEmpty(triggersOfJob)) {
            for (Trigger trigger : triggersOfJob) {
                TriggerKey triggerKey = trigger.getKey();
                scheduler.pauseTrigger(triggerKey);// 停止触发器
                scheduler.unscheduleJob(triggerKey);// 移除触发器
            }
        }
    }

    @Override
    public void pauseTask(String taskId) throws SchedulerException {
        //通过taskId创建JobKey
        JobKey jobKey = new JobKey(taskId, ScheduleConstant.DEFAULT_JOB_GROUP_NAME);
        checkJobKey(jobKey);
        scheduler.pauseJob(jobKey);
        log.info("成功暂停执行({})定时任务", taskId);
    }

    @Override
    public void resumeTask(String taskId) throws SchedulerException {
        //通过taskId创建JobKey
        JobKey jobKey = new JobKey(taskId, ScheduleConstant.DEFAULT_JOB_GROUP_NAME);
        checkJobKey(jobKey);
        scheduler.resumeJob(jobKey);
        log.info("成功继续执行({})定时任务", taskId);
    }


    @Override
    public List<Task> getTaskList() throws SchedulerException {
        List<Task> taskList = new ArrayList<>();
        for (String jobGroupName : scheduler.getJobGroupNames()) {
            for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher.jobGroupEquals(jobGroupName))) {
                Task instance = Task.getInstance(scheduler.getJobDetail(jobKey));
                taskList.add(instance);
            }
        }
        return taskList;
    }
}
